Fixed oversized menus allocated offscreen
authorTristan Van Berkom <tristan.van.berkom@gmail.com>
Sat, 21 Aug 2010 01:15:35 +0000 (21:15 -0400)
committerTristan Van Berkom <tristan.van.berkom@gmail.com>
Sat, 21 Aug 2010 01:18:13 +0000 (21:18 -0400)
Removed the old toplevel window size-request signal and
do the clamping in gtk_menu_get_height_for_width() instead,
also make sure to invalidate the size before doing a new
request just after invoking the delegate menu position func.

gtk/gtkmenu.c

index 03aff5509a6da56e373347002ca99b7d9c32a74f..e258f015fdb5b903cd8596c20fa1c92d6d2b4129 100644 (file)
@@ -1027,28 +1027,6 @@ gtk_menu_window_event (GtkWidget *window,
   return handled;
 }
 
-static void
-gtk_menu_window_size_request (GtkWidget      *window,
-                             GtkRequisition *requisition,
-                             GtkMenu        *menu)
-{
-  GtkMenuPrivate *private = gtk_menu_get_private (menu);
-
-  if (private->have_position)
-    {
-      GdkScreen *screen = gtk_widget_get_screen (window);
-      GdkRectangle monitor;
-      
-      gdk_screen_get_monitor_geometry (screen, private->monitor_num, &monitor);
-
-      if (private->y + requisition->height > monitor.y + monitor.height)
-       requisition->height = monitor.y + monitor.height - private->y;
-
-      if (private->y < monitor.y)
-       requisition->height -= monitor.y - private->y;
-    }
-}
-
 static void
 gtk_menu_init (GtkMenu *menu)
 {
@@ -1066,7 +1044,6 @@ gtk_menu_init (GtkMenu *menu)
                                                   "child", menu,
                                                   NULL),
                                     "signal::event", gtk_menu_window_event, menu,
-                                    "signal::size-request", gtk_menu_window_size_request, menu,
                                     "signal::destroy", gtk_widget_destroyed, &menu->toplevel,
                                     NULL);
   gtk_window_set_resizable (GTK_WINDOW (menu->toplevel), FALSE);
@@ -1641,7 +1618,10 @@ gtk_menu_popup_for_device (GtkMenu             *menu,
     GtkRequisition tmp_request;
     GtkAllocation tmp_allocation = { 0, };
 
-    gtk_size_request_get_size (GTK_SIZE_REQUEST (menu->toplevel), NULL, &tmp_request);
+    /* Instead of trusting the menu position function to queue a resize when the
+     * menu goes out of bounds, invalidate the cached size here. */
+    gtk_widget_queue_resize (GTK_WIDGET (menu));
+    gtk_size_request_get_size (GTK_SIZE_REQUEST (menu->toplevel), &tmp_request, NULL);
     
     tmp_allocation.width = tmp_request.width;
     tmp_allocation.height = tmp_request.height;
@@ -3144,11 +3124,12 @@ gtk_menu_get_height_for_width (GtkSizeRequest      *widget,
                               gint                *minimum_size,
                               gint                *natural_size)
 {
-  GtkMenu  *menu = GTK_MENU (widget);
-  guint    *min_heights, *nat_heights;
-  guint     vertical_padding, border_width;
-  gint      n_heights, i;
-  gint      min_height, nat_height;
+  GtkMenu        *menu = GTK_MENU (widget);
+  GtkMenuPrivate *private = gtk_menu_get_private (menu);
+  guint          *min_heights, *nat_heights;
+  guint           vertical_padding, border_width;
+  gint            n_heights, i;
+  gint            min_height, nat_height;
 
   gtk_widget_style_get (GTK_WIDGET (menu), "vertical-padding", &vertical_padding, NULL);
   border_width = gtk_container_get_border_width (GTK_CONTAINER (menu));
@@ -3164,6 +3145,26 @@ gtk_menu_get_height_for_width (GtkSizeRequest      *widget,
       nat_height += nat_heights[i];
     }
 
+  if (private->have_position)
+    {
+      GdkScreen *screen = gtk_widget_get_screen (menu->toplevel);
+      GdkRectangle monitor;
+      
+      gdk_screen_get_monitor_geometry (screen, private->monitor_num, &monitor);
+
+      if (private->y + min_height > monitor.y + monitor.height)
+       min_height = monitor.y + monitor.height - private->y;
+
+      if (private->y + nat_height > monitor.y + monitor.height)
+       nat_height = monitor.y + monitor.height - private->y;
+
+      if (private->y < monitor.y)
+       {
+         min_height -= monitor.y - private->y;
+         nat_height -= monitor.y - private->y;
+       }
+    }
+
   if (minimum_size)
     *minimum_size = min_height;
 
@@ -4685,7 +4686,7 @@ gtk_menu_position (GtkMenu *menu)
       gtk_window_resize (GTK_WINDOW (menu->tearoff_window),
                         requisition.width, requisition.height);
     }
-  
+
   menu->scroll_offset = scroll_offset;
 }